package com.xiaohong.file.controller;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaohong.file.entity.Result;
import com.xiaohong.file.entity.StatusCode;
import com.xiaohong.file.pojo.File;
import com.xiaohong.file.pojo.GoFastDfsUploadResult;
import com.xiaohong.file.service.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.websocket.server.PathParam;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;

/**
 * @author : xiaohong
 * @date : 2021/6/13 11:48
 */
@RestController
@RequestMapping("/file")
@CrossOrigin
public class GoFastController {

    @Autowired
    private FileService fileService;

    private static final String UPLOAD_PATH = "http://119.29.67.157:8080/xiaohong/upload";
    // 需要内网ip
//    private static final String DELETE_PATH = "http://119.29.67.157:8080/xiaohong/delete";
    private static final String DELETE_PATH = "http://10.0.8.8:8080/xiaohong/delete";
    // 需要内网ip
    private static final String INFO_PATH = "http://10.0.8.8:8080/xiaohong/get_file_info";
    private static final String SECOND_PATH = "http://119.29.67.157:8080/xiaohong/upload";
    private static final String SHOW_PATH = "https://file.xiaohong.work";


    /***
     * 分页查询
     * @return
     */
    @RequestMapping(value = "/callback" )
    public void callback(ServletRequest servletRequest, ServletResponse servletResponse){
        System.out.println("回调函数");
    }


    /***
     * 条件分页关键字查询
     * @param key
     * @param page
     * @param size
     * @return
     */
    @Operation(summary = "条件分页关键字查询",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameters({
            @Parameter(in = ParameterIn.PATH, name = "page", description = "当前页", required = true),
            @Parameter(in = ParameterIn.PATH, name = "size", description = "每页显示条数", required = true)
    })
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<Page> findPageByKey(@RequestParam String key, @PathVariable  int page, @PathVariable  int size){

        Page pageInfo = null;
        if(!StringUtils.isEmpty(key)){
            pageInfo = fileService.findPageByKey(key, page, size);
        }else {
            pageInfo = fileService.findPage(page, size);
        }

        return new Result<Page>(true,StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * 分页查询
     * @param page:当前页
     * @param size:每页显示多少条
     * @return
     */
    @Operation(summary = "分页查询",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @Parameters({
            @Parameter(in = ParameterIn.PATH, name = "page", description = "当前页", required = true),
            @Parameter(in = ParameterIn.PATH, name = "size", description = "每页显示条数", required = true)
    })
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<Page> findPage(@PathVariable  int page, @PathVariable  int size){
        //调用FileService实现分页查询File
        Page pageInfo = fileService.findPage(page, size);
        return new Result<Page>(true,StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * 条件查询
     * @param file
     * @return
     */
    @Operation(summary = "条件查询",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @PostMapping(value = "/search" )
    public Result<List<File>> findList(@RequestBody(required = false) @Parameter(name = "File对象",required = true) File file){
        //调用FileService实现条件查询File
        List<File> list = fileService.findList(file);
        return new Result<List<File>>(true,StatusCode.OK,"查询成功",list);
    }


    /***
     * 根据MD5查询
     * @param
     * @return
     */
    @Operation(summary = "根据MD5查询",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @RequestMapping(value = "/again" )
    public void again(){
        System.out.println("文件秒传");
    }


    /***
     * 根据MD5查询
     * @param md5
     * @return
     */
    @Operation(summary = "根据MD5查询",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @GetMapping(value = "/searchByMD5" )
    public Result<File> findByMD5(String md5){
        File file = new File();
        file.setMd5(md5);
        List<File> list = fileService.findList(file);
        if(list.size() > 0 ){
            return new Result<File>(true,StatusCode.OK,"查询成功",list.get(0));
        }else {
            return new Result<File>(true,StatusCode.ERROR,"查询失败","null");
        }
    }

//    public static void main(String[] args) throws Exception {
//        System.out.println("1");
//        Thread.sleep(2000);
//        System.out.println("2");
//        System.out.println("3");
//        System.out.println("4");
//    }

    /***
     * 新增File数据
     * @param file
     * @return
     */
    @Operation(summary = "添加File",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @PostMapping("/add")
    public Result add(@RequestBody File file){
        try {
            //看看文件是否存在
            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
            CloseableHttpResponse httpResponse = null;
            URIBuilder uriBuilder = new URIBuilder(SECOND_PATH);
            uriBuilder.addParameter("md5",file.getMd5());
            uriBuilder.addParameter("output","json");
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            Thread.sleep(5000); // 休眠五秒后执行
            httpResponse = httpClient.execute(httpGet);
            System.out.println(httpResponse);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                String respStr = EntityUtils.toString(httpResponse.getEntity());
                System.out.println(respStr);
                JSONObject jsonObj = new JSONObject(respStr);
                System.out.println(jsonObj);
                file.setPath(jsonObj.getStr("path"));
                file.setMd5(jsonObj.getStr("md5"));
                file.setFileSize(Integer.parseInt(jsonObj.getStr("size")));
                file.setDomain(jsonObj.getStr("domain"));
                List<File> list = fileService.findList(file);
                if(list.size() > 0 && list != null){
                    // 已存在不管
                    return new Result(true,StatusCode.OK,"重复添加");
                }else {
                    // 第一次上传，新增
                    fileService.add(file);
                    return new Result(true,StatusCode.OK,"添加成功");
                }
            }else {
                System.out.println(EntityUtils.toString(httpResponse.getEntity()));
                return new Result(true,StatusCode.ERROR,"添加失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(true,StatusCode.ERROR,"后台错误,添加失败");
        }

    }


    /***
     * 增加秒传文件File
     * @param file
     * @return
     */
    @Operation(summary = "添加秒传文件File",description = "所需权限：",security ={@SecurityRequirement(name ="Authorization")})
    @PostMapping("/add/quick")
    public Result addQuick(@RequestBody File file){
        File fl = new File();
        fl.setMd5(file.getMd5());
        List<File> list = fileService.findList(fl);
        if (list.size() > 0 && list != null){
            fl.setFileDescription(file.getFileDescription());
            fl.setFileName(file.getFileName());
            List<File> lst = fileService.findList(fl);
            if(lst.size() > 0 && lst != null){
                // 重复添加
                return new Result(true,StatusCode.OK,"重复添加");
            }else {
                // 名称或描述修改了
                fl.setFileSize(list.get(0).getFileSize());
                fl.setDomain(list.get(0).getDomain());
                fl.setPath(list.get(0).getPath());
                fl.setExtension(list.get(0).getExtension());
                fl.setFileGroup(list.get(0).getFileGroup());
                fileService.add(fl);
                return new Result(true,StatusCode.OK,"添加成功");
            }
        }else {
            return new Result(true,StatusCode.ERROR,"第一次添加的扔这干嘛！");
        }
    }

    /**
     * 上传文件
     * @param file
     * @return
     * @throws Exception
     */
    @RequestMapping("/upload")
    public Result upload(MultipartFile file, @PathParam("fileDescription") String fileDescription ) {
        File result = new File();
        try {
            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
            CloseableHttpResponse httpResponse = null;
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(200000)
                    .setSocketTimeout(2000000)
                    .build();
            HttpPost httpPost = new HttpPost(UPLOAD_PATH);
            httpPost.setConfig(requestConfig);
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create()
                    .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                    .setCharset(Charset.forName("UTF-8"))
                    .addTextBody("output", "json")
                    .addBinaryBody("file", file.getInputStream(),
                            ContentType.DEFAULT_BINARY, file.getOriginalFilename());
            httpPost.setEntity(multipartEntityBuilder.build());
            httpResponse = httpClient.execute(httpPost);

            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                String respStr = EntityUtils.toString(httpResponse.getEntity());
                System.out.println(respStr);
                JSONObject jsonObj = new JSONObject(respStr);
                result.setFileGroup("xiaohong");
                result.setFileDescription(fileDescription);
                System.out.println(jsonObj.getStr("src"));
                System.out.println(jsonObj.getStr("src").split("\\."));
                System.out.println(jsonObj.getStr("src").split("\\.").length);
                result.setExtension(jsonObj.getStr("src").split("\\.")[jsonObj.getStr("src").split("\\.").length-1]);
                result.setMd5(jsonObj.getStr("md5"));
//                result.setFileUrl(SHOW_PATH+jsonObj.getStr("src"));
//                result.setFileName(result.getFileUrl().split("/")[result.getFileUrl().split("/").length-1]);
                result.setFileSize(Integer.parseInt(jsonObj.getStr("size")));
                // 添加到数据库
                fileService.add(result);
            }

            httpClient.close();
            httpResponse.close();
            return new Result(true,StatusCode.OK,"上传成功",result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new Result(true,StatusCode.ERROR,"上传失败");
    }


    /**
     * 删除文件
     * @return
     * @throws Exception
     */
    @RequestMapping("/delete")
    public Result delete(String md5, Long id, String path) {
        File fd = new File();
        fd.setMd5(md5);
        List<File> list = fileService.findList(fd);
        if(list.size() == 1){
            try {
                CloseableHttpClient httpClient = HttpClientBuilder.create().build();
                CloseableHttpResponse httpResponse = null;
                RequestConfig requestConfig = RequestConfig.custom()
                        .setConnectTimeout(200000)
                        .setSocketTimeout(2000000)
                        .build();
                HashMap<String, Object> param = new HashMap<>(10);
                URIBuilder uriBuilder = new URIBuilder(DELETE_PATH);
                uriBuilder.addParameter("path",path);
                HttpPost httpPost = new HttpPost(uriBuilder.build());
                httpPost.setConfig(requestConfig);
                httpResponse = httpClient.execute(httpPost);

                if (httpResponse.getStatusLine().getStatusCode() == 200) {
                    String respStr = EntityUtils.toString(httpResponse.getEntity());
                    System.out.println(respStr);
                    JSONObject jsonObj = new JSONObject(respStr);
                    System.out.println("响应状态："+jsonObj.getStr("status"));
                    if(jsonObj.getStr("status").equals("ok")){
                        // 只有一条 删除数据库和文件
                        fileService.delete(id);
                        return new Result(true,StatusCode.OK,"删除成功");
                    }else{
                        return new Result(true,StatusCode.ERROR,"删除文件失败");
                    }
                }

                httpClient.close();
                httpResponse.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return new Result(true,StatusCode.ERROR,"删除文件失败");
        }else if(list.size() > 1){
            // 有多条记录 复用 只删除数据库 不删除文件
            fileService.delete(id);
            return new Result(true,StatusCode.OK,"删除成功");
        }else{
            return new Result(true,StatusCode.ERROR,"未查到文件相关信息");
        }
    }

    /**
     * 获取文件信息
     * @param md5
     * @return
     * @throws Exception
     */
    @RequestMapping("/info")
    public Result getFileInfo(String md5) {
        File fd = new File();
        fd.setMd5(md5);
        List<File> list = fileService.findList(fd);
        if(list.size() > 0 && list != null){
            return new Result(true,StatusCode.OK,"获取文件信息成功",list.get(0));
        }else{
            return new Result(true,StatusCode.ERROR,"未查到文件相关信息");
        }
//        String result = "";
//        try {
//            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
//            CloseableHttpResponse httpResponse = null;
//            RequestConfig requestConfig = RequestConfig.custom()
//                    .setConnectTimeout(200000)
//                    .setSocketTimeout(2000000)
//                    .build();
//            HashMap<String, Object> param = new HashMap<>(10);
//            URIBuilder uriBuilder = new URIBuilder(INFO_PATH);
//            uriBuilder.addParameter("md5",md5);
//            HttpPost httpPost = new HttpPost(uriBuilder.build());
//            httpPost.setConfig(requestConfig);
//            httpResponse = httpClient.execute(httpPost);
//
//            if (httpResponse.getStatusLine().getStatusCode() == 200) {
//                String respStr = EntityUtils.toString(httpResponse.getEntity());
//                System.out.println(respStr);
//                result = respStr;
//            }
//
//            httpClient.close();
//            httpResponse.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return result;
    }


}
